#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <getopt.h>
#include <stdlib.h>


#define	BACKLOG	 13
#define	Sock_Port 9806
#define BUF_SIZE 1024

#define	MSG_STR	"Hello Client Welcome to Connect...!"



void print_usage(const char *program_name) 
{  
		printf("\n%s -- 1.0.0(2018.11.4)\n", program_name);  
        	printf(" Usage: %s -p <server_port>  [-h <server_use_help>]\n", program_name);  
		printf("	-p --port	the server listen port\n") ;
		printf("	-h --help	the server file how to use\n");  

		return ;
}  






int main( int argc, char **argv )
{
	int listen_fd,client_fd = -1 ;
	struct sockaddr_in	serv_addr ;
	struct	sockaddr_in	cli_addr ;
	socklen_t		cli_addr_len ;
	int 			rv = -1 ;
	char			buf[BUF_SIZE] ;
	int			opt = -1 ;	
	int			port = 0 ;


const char *short_opts = "p:h";  


const struct option long_opts[] = 	{  

						{"help", no_argument, NULL, 'h'},  

				     		{ "port", required_argument, NULL, 'p'},  

					       {0, 0, 0, 0}  
			        	};  


while ((opt= getopt_long(argc, argv, short_opts, long_opts,NULL)) != -1) 
	{
		switch (opt) 
		{
			case 'p':
				port = atoi(optarg);
				break ;

			case 'h':
				print_usage(argv[0]) ;
				return 0;
		
		
		}			
	

	}

	if( !port )
	{
		print_usage(argv[0]);
		return 0;
	
	}



	listen_fd = socket(AF_INET, SOCK_STREAM, 0) ;
	if(listen_fd < 0)
	{
		printf("creat socket failure : %s \n", strerror(errno) ) ;
		return -1 ;
	
	}
	printf("creat socket suceeful, listen_fd descriptor[%d]\n", listen_fd) ;

	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET ;
	serv_addr.sin_port = htons(port) ;
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY) ;
	memset(&cli_addr, 0, sizeof(serv_addr));


	 int reuse = 1 ;
	 setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));

	if ( bind(listen_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr) ) < 0 )
	{
		printf("socket bind failure : %s\n", strerror(errno) ) ;
		goto cleanup ;
	}
	

	if ( listen(listen_fd ,BACKLOG) < 0 )
	{	
		printf("socket listen failure: %s\n", strerror(errno) ) ;
		goto cleanup ;
	}


	while(1)
	{
		printf("\n/********************************************************************/\n") ;
		printf("\n Server Start Work, Server port:%d, And Waiting The Client Connect ...\n", port) ;
		client_fd = accept(listen_fd,(struct sockaddr*) &cli_addr, &cli_addr_len) ; 
		if(client_fd < 0)
		{
			printf("accept failure: %s\n", strerror(errno)) ;
			return -1 ;
		}
		printf("accept succeful, client [%s:%d] \n", inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port) ) ;

		memset(buf, 0, sizeof(buf)) ;

		rv = read (client_fd, buf, sizeof(buf)) ;
		if(rv < 0)
		{
			printf("read from client failure: %s\n", strerror(errno)) ;
			goto cleanup ;
		}

		if(rv == 0)
		{
			printf("client connect failure!\n") ;
			continue ;
		}

		printf("\n %d byte read from client : '%s' " ,rv, buf) ;
		
		if (write(client_fd, MSG_STR, strlen(MSG_STR) ) < 0)
		{
			printf("write to client failed: %s\n", strerror(errno)) ;
			close(client_fd) ;
			continue ;
		}

			
		sleep(2) ;

		close(client_fd) ;


	}

cleanup:
	close(listen_fd) ;
	close(client_fd) ;
	



	return 0 ;
}

